import { ZoomInOutlined, ZoomOutOutlined } from '@ant-design/icons'
import G6, { EdgeConfig, Graph, NodeConfig } from '@antv/g6'
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
import { EntityItem } from '@common/const/type'
import { useFetch } from '@common/hooks/http'
import { $t } from '@common/locales'
import { getNodeSpacing } from '@common/utils/systemRunning'
import { RouterParams } from '@core/components/aoplatform/RenderRoutes'
import { App, Button } from 'antd'
import { debounce } from 'lodash-es'
import { useCallback, useEffect, useRef, useState } from 'react'
import { useParams } from 'react-router-dom'
import { RELATIVE_PICTURE_NODE_FONTSIZE } from '../../const/system-running/const'
import { GraphData } from '../../const/system-running/type'
import { SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP } from '../../const/system/const'
import { SystemTopologyResponse } from '../../const/system/type'
import { useSystemContext } from '../../contexts/SystemContext'

export default function SystemTopology() {
  const { message } = App.useApp()
  const { serviceId, teamId } = useParams<RouterParams>()
  const graphContainerRef = useRef<HTMLDivElement>(null)
  const graphRef = useRef<Graph>(null)
  const [graphData, setGraphData] = useState<GraphData>()
  const [graph, setGraph] = useState<Graph | null>(null)
  const { fetchData } = useFetch()
  const { systemInfo } = useSystemContext()
  const [zoomNum, setZoomNum] = useState<number>(1)


  const getNodeData = () => {
    fetchData<BasicResponse<SystemTopologyResponse>>('service/topology', {
      method: 'GET',
      eoParams: { service: serviceId, team: teamId }
    }).then((response) => {
      const { code, data, msg } = response
      if (code === STATUS_CODE.SUCCESS) {
        setGraphData(transformData({ ...data, currentSystem: { id: serviceId, name: systemInfo?.name || '' } }))
      } else {
        message.error(msg || $t(RESPONSE_TIPS.error))
      }
    })
  }

  const initGraph = () => {
    return new G6.Graph({
      container: graphContainerRef.current!,
      layout: {
        type: 'dagre',
        ranksep: 20,
        controlPoints: true,
        preventOverlap: true,
        padding: [20, 20, 20, 20],
        nodeStrength: (d: unknown) => {
          if (d.isLeaf) {
            return -50
          }
          return -10
        },
        fitCenter: true
      },
      defaultNode: {
        size: [20, 20],
        style: {
          radius: 5,
          lineWidth: 1,
          fillOpacity: 1
        },
        labelCfg: {
          style: {
            fontSize: RELATIVE_PICTURE_NODE_FONTSIZE,
            fill: '#666'
          },
          position: 'bottom',
          offset: 12
        }
      },
      defaultEdge: {
        type: 'cubic-vertical',
        style: {
          radius: 20,
          offset: 45,
          endArrow: true,
          lineWidth: 2
        }
      },
      modes: {
        default: ['drag-canvas', 'zoom-canvas', 'drag-node']
      }
    })
  }

  const handleWindowResize = useCallback(
    debounce(() => {
      if (graphContainerRef.current && graphRef.current && !graphRef.current?.get('destroyed')) {
        graphRef.current.changeSize(graphContainerRef.current.offsetWidth, graphContainerRef.current.offsetHeight)
        graphRef.current?.fitCenter()
      }
    }, 400),
    []
  )

  useEffect(() => {
    getNodeData()
  }, [serviceId])

  useEffect(() => {
    // 初始化 G6 图
    const graph = initGraph()
    graph.setMaxZoom(3)
    graph.setMinZoom(0.2)
    setGraph(graph)
    ;// eslint-disable-next-line @typescript-eslint/ban-ts-comment
    (graphRef as any).current = graph

    graph.fitCenter()
    handleWindowResize()
    // 添加窗口大小变化的监听器
    window.addEventListener('resize', handleWindowResize)

    // 组件卸载时清理资源
    return () => {
      window.removeEventListener('resize', handleWindowResize)
      if (graphRef.current) {
        graphRef.current.destroy()
      }
    }
  }, [])

  useEffect(() => {
    if (!graph) return
    graph.clear()
    graph.data(graphData)
    const { nodes } = graphData as GraphData

    if (nodes?.length) {
      graph.updateLayout({
        nodeSpacing: getNodeSpacing(nodes.length)
      })
    }

    graph.render()
    setTimeout(() => {
      graph.fitCenter()
    })
  }, [graphData])

  /**
   * @description 更新缩放比例
   */
  const updateZoomTo = (increase: boolean) => {
    if ((increase && zoomNum * 10 >= 20) || (!increase && zoomNum * 10 <= 2)) return
    setZoomNum(increase ? (zoomNum * 10 + 2) / 10 : (zoomNum * 10 - 2) / 10)
    graph?.zoomTo(increase ? (zoomNum * 10 + 2) / 10 : (zoomNum * 10 - 2) / 10)
  }

  return (
    <div className="w-full h-full bg-MAIN_BG">
      <div className="mt-[10px] ml-[10px] w-[100%-192px] absolute top-[143px] right-0">
        <div className="flex justify-between">
          <div></div>
          <div className="border border-solid border-color-base rounded mr-[20px] z-[999] h-8">
            <Button
              id="zoom-in-button"
              type="text"
              title="放大"
              icon={<ZoomInOutlined />}
              onClick={() => updateZoomTo(true)}
            />
            <Button
              id="zoom-out-button"
              type="text"
              title="缩小"
              icon={<ZoomOutOutlined />}
              onClick={() => updateZoomTo(false)}
            />
          </div>
        </div>
      </div>
      <div className="w-full h-full" ref={graphContainerRef}></div>
      {/* <div className="px-[10px] py-[20px] pb-[30px] flex flex-wrap items-center justify-center ">
        {Object.entries(SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP).map(([_, config]) => (
          <div key={config.name} className="flex items-center mr-[10px]">
            <span
              className="inline-block w-[20px] h-[20px] rounded-full mr-2"
              style={
                {border:`1px solid ${config.stroke}`,
                backgroundColor: config.fill}
              }></span>
              <span className="white-space-nowrap">{config.name}</span></div>))}
      </div> */}
    </div>
  )
}

function transformData(response: SystemTopologyResponse & { currentSystem: EntityItem }): {
  nodes: NodeConfig[]
  edges: EdgeConfig[]
} {
  const nodes: NodeConfig[] = []
  const edges: EdgeConfig[] = []

  // 添加当前服务节点
  nodes.push({
    id: response.currentSystem.id,
    label: `${response.currentSystem.name}`,
    type: 'curProject',
    style: {
      // fill: SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP.curProject.fill,
      // stroke: SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP.curProject.stroke,
    }
  })

  // response.services.forEach(service =>{
  //   // nodes.push({
  //   //   id: service.id,
  //   //   label: `${service.name}`,
  //   //   type: 'subscriberService',
  //   //   style: {
  //   //     fill: SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP.subscriberService.fill,
  //   //     stroke: SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP.subscriberService.stroke,
  //   //   },
  //   // });
  //   edges.push({
  //     source: service.id,
  //     // source: service.id,
  //     target: response.currentSystem.id,
  //     type: 'subscribes',
  //     style:{
  //       lineDash:[4,4],
  //       endArrow:false,
  //       stroke: SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP.subscriberService.stroke, // 订阅服务节点使用蓝色
  //     }
  //   });
  // })

  // 添加订阅者节点和边
  response.subscribers.forEach((subscriber) => {
    nodes.push({
      id: subscriber.service.id,
      label: `${subscriber.service.name}`,
      type: 'subscriberProject',
      style: {
        fill: SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP.subscriberProject.fill,
        stroke: SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP.subscriberProject.stroke
      }
    })
    subscriber.services.forEach((serviceData) => {
      const service = response.services.find((s) => s.id === serviceData.id)
      if (service) {
        edges.push({
          source: subscriber.service.id,
          target: response.currentSystem.id,
          type: 'subscribes',
          style: {
            endArrow: true,
            stroke: SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP.subscriberProject.stroke // 订阅服务节点使用蓝色
          }
        })
        // edges.push({
        //   source: subscriber.service.id,
        //   target: service.id,
        //   type: 'subscribes',
        //   style:{
        //     stroke: SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP.subscriberProject.stroke, // 订阅服务节点使用蓝色
        //   }
        // });
        // edges.push({
        //   source: service.id,
        //   target: response.currentSystem.id,
        //   type: 'subscribes',
        //   style:{
        //     stroke: SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP.subscriberService.stroke, // 订阅服务节点使用蓝色
        //   }
        // });
      }
    })
  })

  // 添加调用者节点和边
  response.invoke?.forEach((invoker) => {
    nodes.push({
      id: invoker.service.id,
      label: `${invoker.service.name}`,
      type: 'invokeProject',
      style: {
        fill: SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP.invokeProject.fill,
        stroke: SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP.invokeProject.stroke
      }
    })

    edges.push({
      source: response.currentSystem.id,
      target: invoker.service.id,
      type: 'subscribes',
      style: {
        endArrow: true,
        stroke: SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP.invokeProject.stroke // 订阅服务节点使用蓝色
      }
    })
    // invoker.services.forEach(serviceData => {
    //     nodes.push({
    //       id: serviceData.id,
    //       label: `服务: ${serviceData.name}`,
    //       type: 'invokeService',
    //       style: {
    //         fill: SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP.invokeService.fill,
    //         stroke: SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP.invokeService.stroke,
    //       },
    //     });

    //     edges.push({
    //       source: response.currentSystem.id,
    //       target: serviceData.id,
    //       type: 'subscribes',
    //       style:{
    //         lineDash:[4,4],
    //         endArrow:false,
    //         stroke: SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP.invokeService.stroke, // 订阅服务节点使用蓝色
    //       }
    //     });
    //     edges.push({
    //       source: serviceData.id,
    //       target: invoker.service.id,
    //       type: 'invokes',
    //       style:{
    //         stroke: SYSTEM_TOPOLOGY_NODE_TYPE_COLOR_MAP.invokeProject.stroke, // 订阅服务节点使用蓝色
    //       }
    //     });
    // });
  })

  return { nodes, edges }
}
